package com.yanqu.road.server.logic;

import com.google.protobuf.AbstractMessage;
import com.google.protobuf.ByteString;
import com.google.protobuf.GeneratedMessage;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.logic.helper.UnionActivityGroupHelper;
import com.yanqu.road.pb.server.ServerProto;
import com.yanqu.road.pb.union.UnionActivityGroupProto;
import com.yanqu.road.server.CrossBaseServer;
import com.yanqu.road.server.cross.service.*;
import com.yanqu.road.server.cross3server.conn.Cross3ConnSet;
import com.yanqu.road.server.connect.CrossAgentLinkedControl;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.server.manager.activity.snowgarden.CrossActivityMallDayBuyMgr;
import com.yanqu.road.server.manager.activity.zhenhuan.CrossZhenHuanMgr;
import com.yanqu.road.server.manager.group.service.GetGroupChatListByUserIdCmdService;
import com.yanqu.road.server.manager.tomb.TombServiceMgr;
import com.yanqu.road.server.manager.union.service.GetUnionMemberChatListByUserIdCmdService;
import com.yanqu.road.server.manager.unioncampwar.CrossUnionCampWarMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.protocol.AgentProtocol;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.server.protocol.GameProtocol;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.sync.message.Caller;
import com.yanqu.road.sync.message.ResultProcessor;
import com.yanqu.road.sync.message.Service;
import com.yanqu.road.sync.message.SyncResponse;

import com.yanqu.road.utils.YanQuMessageUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.*;
import java.util.concurrent.CompletableFuture;

public class MessageHelper {

	private static Logger logger = LogManager.getLogger(MessageHelper.class.getName());


    private static Service syncMessageService = new Service();

    private static Caller syncMessageCaller = new Caller();

	public static void sendPacket(long serverId, long userId, YanQuMessage packet) {
        if (isChannelCode(packet.getCode())) {
            return;
        }
		CrossAgentLinkedControl.send(serverId, userId, packet);
	}

	public static void sendAllServer(YanQuMessage message) {
        if (isChannelCode(message.getCode())) {
            return;
        }
		CrossAgentLinkedControl.sendToAll(message);
	}

    public static void sendChannelServer(YanQuMessage message) {
        if (!isChannelCode(message.getCode())) {
            return;
        }
        // 目前只有一台，直接发全部就行
        Cross3ConnSet.sendToAll(message);
    }

    /**
     * 是否跨地区协议
     */
    public static boolean isChannelCode(int code) {
        return code > 60000 && code < 65000;
    }

    /**
     * 商会跨服 发消息到 活动跨服
     *
     * @param appointCrossId 小于等于0时，自动根据groupId获取crossId
     * @param groupId        不填groupId的话，活动跨服cmd取不到groupId
     */
    public static void sendUnionActivityGroupPacket(long serverId, long userId, int code, AbstractMessage.Builder<?> messageBuilder, int activityId, int appointCrossId, int groupId) {
        if (isChannelCode(code)) {
            return;
        }

        boolean isActivityCrossCode = code > 40000 && code < 50000;
        if (!isActivityCrossCode) {
            throw new RuntimeException("============================= 这个不是活动跨服协议ID，用这个发要死循环了 =============================");
        }

        if (groupId < 0) {
            groupId = UnionActivityGroupHelper.NO_GROUP_ID;
        }

        UnionActivityGroupProto.BaseUnionActivityGroupMsg.Builder newBuilder = UnionActivityGroupProto.BaseUnionActivityGroupMsg.newBuilder()
                .setActivityId(activityId)
                .setGroupId(groupId)
                .setCode(code)
                .setMsg(messageBuilder.build().toByteString());
        if (appointCrossId > 0) {
            newBuilder.setCrossId(appointCrossId);
        }
        YanQuMessage message = YanQuMessageUtils.buildMessage(AgentProtocol.A_UNION_ACTIVITY_GROUP_TRANSFER, newBuilder);
        CrossAgentLinkedControl.send(serverId, userId, message);
    }

    public static void initCrossServiceCommand() {
        syncMessageService.addCrossServiceCommand(CrossProtocol.C_UNION_RANK_TOP, new UnionRankTopICrossServiceCmd());
        syncMessageService.addCrossServiceCommand(CrossProtocol.C2_CROSS_GET_USER_ACTIVITY_RANK_SYNC, new CrossGetUserActivityRankServiceCmd());
        syncMessageService.addCrossServiceCommand(CrossProtocol.C2_CROSS_GET_ACTIVITY_RANK_SYNC, new CrossGetActivityRankServiceCmd());

        TombServiceMgr.initService(syncMessageService);
//        CricketServiceMgr.initService(syncMessageService);
//        CricketCenter2ServiceMgr.initService(syncMessageService);
//        syncMessageService.addCrossServiceCommand(CrossProtocol.C_PEAK_STRONGHOLD_NOTIFY_UPDATE_MEMBER_DEFEND_RESP, new PeakHoldUpdateDefendCrossServiceCmd());
        syncMessageService.addCrossServiceCommand(CrossProtocol.C_UNION_MEMBER_CHAT_LIST_BY_USERID, new GetUnionMemberChatListByUserIdCmdService());
        syncMessageService.addCrossServiceCommand(CrossProtocol.C_CROSS_GROUP_CHAT_LIST_BY_USERID, new GetGroupChatListByUserIdCmdService());
        syncMessageService.addCrossServiceCommand(Protocol.C3_UNION_GET_UNION_MEMBER_USER_ID, new CrossGetUnionMemberUserIdServiceCmd());
        CrossUnionCampWarMgr.initService(syncMessageService);

        CrossActivityMallDayBuyMgr.initService(syncMessageService);

        CrossZhenHuanMgr.initService(syncMessageService);
    }

    public static Service getSyncMessageProvider() {
        return syncMessageService;
    }

    public static Caller getSyncMessageCaller() {
        return syncMessageCaller;
    }

    public static CompletableFuture<SyncResponse> sendToGameServer(long forwardServerId, int code, int activityId, long userId, GeneratedMessage.Builder<?> requestBuilder, GeneratedMessage.Builder<?> responseBuilder) {
        long serverId = CrossBaseServer.getInstance().getServerId();
        ResultProcessor resultProcessor = syncMessageCaller.sendMsgSync(serverId, forwardServerId, userId, code, GameProtocol.S_GAME_SERVICE_HANDLER, activityId, requestBuilder, responseBuilder);
        YanQuMessage request = resultProcessor.getRequest();
        sendPacket(forwardServerId, 0, request);
        return resultProcessor.getCompletableFuture();
    }

    public static CompletableFuture<SyncResponse> sendToCross3Server(long forwardServerId, int code, int activityId, long userId, GeneratedMessage.Builder<?> requestBuilder, GeneratedMessage.Builder<?> responseBuilder) {
        long serverId = CrossBaseServer.getInstance().getServerId();
        ResultProcessor resultProcessor = syncMessageCaller.sendMsgSync(serverId, forwardServerId, userId, code, Protocol.C3_CROSS_REQ_HANDLER, activityId, requestBuilder, responseBuilder);
        YanQuMessage request = resultProcessor.getRequest();
        sendPacket(forwardServerId, 0, request);
        return resultProcessor.getCompletableFuture();
    }


    /**
     * 发包（单玩家）
     *
     * @param code           消息号
     * @param messageBuilder 消息体
     * @param userId         用户
     */
    public static void sendPacket(int code, AbstractMessage.Builder<?> messageBuilder, long userId) {
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if (userBaseInfo == null) {
            return;
        }
        YanQuMessage message = YanQuMessageUtils.buildMessage(code, messageBuilder);
        sendPacket(userBaseInfo.getServerId(), userId, message);
    }

    /**
     * 批量发包
     *
     * @param code           消息号
     * @param messageBuilder 消息体
     * @param userIdList     用户列表
     */
    public static void sendPacketToAll(int code, AbstractMessage.Builder<?> messageBuilder, Collection<Long> userIdList) {
        sendPacketToAll(code, messageBuilder, userIdList, false);
    }

    /**
     * 批量发包
     *
     * @param code           消息号
     * @param messageBuilder 消息体
     * @param userIdList     用户列表
     * @param userIdList     是否同步离线玩家
     */
    public static void sendPacketToAll(int code, AbstractMessage.Builder<?> messageBuilder, Collection<Long> userIdList, boolean syncOffLineUser) {
        if (userIdList == null || userIdList.isEmpty()) {
            return;
        }
        Map<Long, List<Long>> userIdMap  = new HashMap<>();
        for (Long userId : userIdList) {
            long tmpServerId = CrossUserMgr.getServerIdByUserId(userId);
            if (tmpServerId == 0) {
                continue;
            }
            userIdMap.computeIfAbsent(tmpServerId, k -> new ArrayList<>()).add(userId);
        }
        for (Map.Entry<Long, List<Long>> entry : userIdMap.entrySet()) {
            long serverId = entry.getKey();
            sendPacketToAll(code, messageBuilder.build().toByteString(), serverId, entry.getValue(), syncOffLineUser);
        }
    }

    public static void sendPacketToAll(int code, ByteString byteString, long serverId, Collection<Long> userIdList, boolean syncOffLineUser) {
        if (userIdList == null || userIdList.isEmpty()) {
            return;
        }
        ServerProto.GameAgentTransferMsg.Builder agentMsg = ServerProto.GameAgentTransferMsg.newBuilder();
        agentMsg.setCode(code);
        agentMsg.addAllUserId(userIdList);
        agentMsg.setMsg(byteString);
        agentMsg.setSyncOffLineUser(syncOffLineUser);
        YanQuMessage message = YanQuMessageUtils.buildMessage(AgentProtocol.A_GAME_TRANSFER, agentMsg);
        // 获取下分组的服务器列表
        sendPacket(serverId, 0, message);
    }

    public static void sendPacketToActivityAll(int code, AbstractMessage.Builder<?> messageBuilder, ActivityInfo activityInfo) {
        ServerProto.GameAgentTransferMsg.Builder agentMsg = ServerProto.GameAgentTransferMsg.newBuilder();
        agentMsg.setCode(code);
        agentMsg.setMsg(messageBuilder.build().toByteString());
        Set<Long> serverIdList = new HashSet<>();
        YanQuMessage message = YanQuMessageUtils.buildMessage(AgentProtocol.A_GAME_TRANSFER, agentMsg);
        // 获取下分组的服务器列表
        for (Long serverId : activityInfo.getServerIdList()) {
            sendPacket(serverId, 0, message);
        }
    }

}
